
#ifndef QT_MYBATIS_PLUS_H
#define QT_MYBATIS_PLUS_H

#include <QObject>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QMap>
#include <QVector>
#include <QDateTime>
#include <QSet>
#include <QThread>
#include <QDebug>
#include <QCoreApplication>
#include <QCache>
#include <mutex>
#include <type_traits>
#include <stdexcept>
#include "qconnectionpool.h"
#include "qconnectionpoolmuti.h"
#include "qforeach.h"
#include "securityutils.h"
#include "transaction.h"
#include "sqlinjectionexception.h"
#include "metadatautils.h"


namespace QtMyBatisPlus {

// 前置声明
class QueryWrapper;


// QVariantMap 合并工具类
class QVariantUtils {
public:
    static QVariantMap merge(const QVariantMap& base, const QVariantMap& other) {
        QVariantMap result = base;

        for (auto it = other.constBegin(); it != other.constEnd(); ++it) {
            const QString& key = it.key();
            const QVariant& value = it.value();

            if (result.contains(key)) {
                int suffix = 1;
                QString newKey;
                do {
                    newKey = QString("%1_%2").arg(key).arg(suffix++);
                } while (result.contains(newKey));
                result.insert(newKey, value);
            } else {
                result.insert(key, value);
            }
        }

        return result;
    }

    static QVariantMap safeMerge(const QList<QVariantMap>& maps) {
        QVariantMap result;
        for (const auto& map : maps) {
            result = merge(result, map);
        }
        return result;
    }

    static QVariantMap mergeWithPrefix(const QVariantMap& base,
                                       const QVariantMap& other,
                                       const QString& prefix) {
        QVariantMap result = base;

        for (auto it = other.constBegin(); it != other.constEnd(); ++it) {
            QString prefixedKey = prefix.isEmpty() ? it.key() : prefix + "_" + it.key();
            result.insert(prefixedKey, it.value());
        }

        return result;
    }
};

// 条件构造器
// 条件构造器
class QueryWrapper {
public:
    QueryWrapper();

    // 基础比较操作
    QueryWrapper& eq(const QString& column, const QVariant& value);
    QueryWrapper& ne(const QString& column, const QVariant& value);
    QueryWrapper& gt(const QString& column, const QVariant& value);
    QueryWrapper& ge(const QString& column, const QVariant& value);
    QueryWrapper& lt(const QString& column, const QVariant& value);
    QueryWrapper& le(const QString& column, const QVariant& value);

    // 范围操作
    QueryWrapper& between(const QString& column, const QVariant& low, const QVariant& high);
    QueryWrapper& notBetween(const QString& column, const QVariant& low, const QVariant& high);

    // 集合操作
    QueryWrapper& in(const QString& column, const QVariantList& values);
    QueryWrapper& notIn(const QString& column, const QVariantList& values);

    // 模糊匹配
    QueryWrapper& like(const QString& column, const QString& value);
    QueryWrapper& notLike(const QString& column, const QString& value);
    QueryWrapper& startsWith(const QString& column, const QString& value);
    QueryWrapper& endsWith(const QString& column, const QString& value);

    // 空值检查
    QueryWrapper& isNull(const QString& column);
    QueryWrapper& isNotNull(const QString& column);

    // 逻辑操作
    QueryWrapper& orCondition(const QueryWrapper& other);
    QueryWrapper& orNew(const QueryWrapper& other);
    QueryWrapper& notCondition(const QueryWrapper& other);

    // 排序和分组
    QueryWrapper& orderByAsc(const QString& column);
    QueryWrapper& orderByDesc(const QString& column);
    QueryWrapper& groupBy(const QString& column);

    // 分页
    QueryWrapper& page(int pageNum, int pageSize);

    // SQL构建
    QString buildWhereClause() const;
    QString buildSqlClause() const;

    // 参数管理
    QVariantMap allParams() const;
    void addExtraParam(const QString& key, const QVariant& value);
    QVariantMap allParamsWithExtra() const;

private:
    void addCondition(const QString& column, const QString& op, const QVariant& value);
    QString sanitizeKey(const QString& key) const;

    QStringList m_conditions;
    QList<QueryWrapper> m_orConditions;
    QVariantMap m_params;
    QVariantMap m_extraParams;
    QString m_groupBy;
    QString m_orderBy;
    int m_offset = 0;
    int m_limit = 0;
};

// 基础Mapper类
template<typename T>
class BaseMapper {
public:
    BaseMapper(){
        pool.ConnectionPool(DB_SQLSERVER)->setSqlServerPara("sa", "123456", "localhost", 3306, "Test");
        m_connection = pool.ConnectionPool(DB_SQLSERVER)->openConnection();
    };
    virtual ~BaseMapper(){
        pool.GetPool(DB_SQLSERVER)->closeConnection(m_connection);
    };

    // CRUD操作
    bool insert(T& entity);
    bool insertBatch(QList<T>& entities);
    bool updateById(T& entity);
    bool updateByWrapper(T& entity, const QueryWrapper& wrapper);
    bool deleteById(int id);
    int deleteByWrapper(const QueryWrapper& wrapper);

    // 查询操作
    T selectById(int id);
    QList<T> selectList(const QueryWrapper& wrapper = QueryWrapper());
    T selectOne(const QueryWrapper& wrapper = QueryWrapper());
    int selectCount(const QueryWrapper& wrapper = QueryWrapper());
    bool exists(const QueryWrapper& wrapper = QueryWrapper());

    // 事务管理
    Transaction beginTransaction();

protected:
    // SQL构建
    virtual QString buildInsertSql(const T& entity);
    virtual QString buildUpdateSql(const T& entity);

    // 参数绑定
    virtual void bindInsertParams(QSqlQuery& query, T& entity);
    virtual void bindUpdateParams(QSqlQuery& query, T& entity);

    // 实体提取
    virtual T extractEntity(const QSqlQuery& query);

    // 参数绑定工具
    void bindParams(QSqlQuery& query, const QVariantMap& params);
    void handleQueryError(const QSqlQuery& query);

    // 安全验证
    void validateTableName() const;
    void validateColumnName(const QString& column) const;
    void validateValue(const QVariant& value) const;

    // 实体操作
    QVariantMap entityToMap(T& entity);
    void mapToEntity(const QVariantMap& map, T& entity);
private:
    QSqlDatabase m_connection;
    QConnectionPoolMuti pool ; //表示多个数据库连接池，有可能是Sqlite或者mysql或者SQLserver，后面的代码要精雕细琢

};


/********************* BaseMapper 实现 *********************/
template<typename T>
void BaseMapper<T>::validateTableName() const {
    QString table = MetaDataUtils::tableName<T>();
    if (!SecurityUtils::isValidTableName(table)) {
        throw SqlInjectionException("Invalid table name: " + table.toStdString());
    }
}

template<typename T>
void BaseMapper<T>::validateColumnName(const QString& column) const {
    if (!SecurityUtils::isValidColumnName(column)) {
        throw SqlInjectionException("Invalid column name: " + column.toStdString());
    }
}

template<typename T>
void BaseMapper<T>::validateValue(const QVariant& value) const {
    if (!SecurityUtils::isSafeValue(value)) {
        throw SqlInjectionException("Unsafe value detected");
    }
}

template<typename T>
bool BaseMapper<T>::insert(T& entity) {
    validateTableName();
    QSqlQuery query(m_connection);
    QString sql = buildInsertSql(entity);

    if (!query.prepare(sql)) {
        qWarning() << "Prepare insert SQL failed:" << query.lastError().text();
        return false;
    }

    bindInsertParams(query, entity);

    if (!query.exec()) {
        handleQueryError(query);
        return false;
    }
    return true;
}

template<typename T>
bool BaseMapper<T>::insertBatch(QList<T>& entities) {
    if (entities.isEmpty()) {
        return true;
    }

    Transaction transaction = beginTransaction();
    try {
        for (T& entity : entities) {
            if (!insert(entity)) {
                throw std::runtime_error("Batch insert failed");
            }
        }
        transaction.commit();
        return true;
    } catch (const std::exception& e) {
        transaction.rollback();
        qCritical() << "Batch insert failed:" << e.what();
        return false;
    }
}

template<typename T>
bool BaseMapper<T>::updateById(T& entity) {
    validateTableName();

    // 自动填充更新时间
    //auto now = QDateTime::currentDateTime();
    //const QMetaObject* meta = &T::staticMetaObject;

    // for (int i = 0; i < meta->propertyCount(); ++i) {
    //     QMetaProperty prop = meta->property(i);
    //     QByteArray propName = prop.name();

    //     // if (MetaDataUtils::isUpdateTime<T>(propName)) {
    //     //     prop.writeOnGadget(&entity, now);
    //     // }
    // }

    QSqlQuery query(m_connection);
    QString sql = buildUpdateSql(entity);

    if (!query.prepare(sql)) {
        qWarning() << "Prepare update SQL failed:" << query.lastError().text();
        return false;
    }

    bindUpdateParams(query, entity);
    if (!query.exec()) {
        handleQueryError(query);
        return false;
    }

    return query.numRowsAffected() > 0;
}

template<typename T>
bool BaseMapper<T>::updateByWrapper(T& entity, const QueryWrapper& wrapper) {
    validateTableName();

    // 自动填充更新时间
    //auto now = QDateTime::currentDateTime();
    const QMetaObject* meta = &T::staticMetaObject;

    QSqlQuery query(m_connection);
    //QVariantMap entityMap = entityToMap(entity);
    QVariantMap params = wrapper.allParamsWithExtra();
    //QStringList columns;
    //QStringList placeholders;

    // 构建SET子句
    QStringList setClauses;
    QStringList columns = MetaDataUtils::columnMap<T>();
    QStringList defaultColumns = MetaDataUtils::DefaultMap<T>();
    QString primaryKey = MetaDataUtils::getPrimaryKeyMap<T>();
    QString autoIncrement = MetaDataUtils::getAutoIncrement<T>(); //如果是自增长的键，不能更新


    QVariantMap defaultMapValue = MetaDataUtils::GetDefaultMapValue<T>(entity) ;
    for (int i = 0; i < meta->propertyCount(); ++i) {
        QMetaProperty prop = meta->property(i);
        QByteArray propName = prop.name();
        QVariant value = prop.readOnGadget(&entity);

        if(!defaultColumns.contains(propName))
        {
            validateColumnName(propName);
            //columns << column;
            //placeholders << ":" + propName; //没有default
            //setClauses.append(QString("%1 = :%2").arg(propName).arg(propName));
            setClauses.append(QString("%1 = :SET_%2").arg(propName).arg(propName));
        }else if(primaryKey == propName){ //如果是主键的话，不做处理
            continue;
        }else if(autoIncrement == propName){
            //如果是自增长的键，不能更新
            //qDebug() << "auto increment column:" << propName << " cannot be updated." << Qt::endl;
            continue; //跳过自增长列)
        }else if(defaultMapValue[propName].toInt() != 0 ){
            validateColumnName(propName);
            //columns << column;
            //placeholders << ":" + propName;
            setClauses.append(QString("%1 = :SET_%2").arg(propName).arg(propName));
            //如果是主键的话，不应该set的
        }

        //&& primaryKey["PrimaryKey"] != column
        // QString column = columnMap.value(it.key(), it.key());
        // QString paramKey = "set_" + it.key();

        //setClauses.append(QString("%1 = :%2").arg(column).arg(paramKey));
        //params[paramKey] = it.value();
    }

    QString wrapperStr = wrapper.buildWhereClause();
    QString sql = QString("UPDATE %1 SET %2 %3")
                      .arg(MetaDataUtils::tableName<T>())
                      .arg(setClauses.join(", "))
                      .arg(wrapper.buildWhereClause());

    // QString sql = QString("UPDATE %1 SET %2 %3")
    //                   .arg(MetaDataUtils::tableName<T>())
    //                   .arg(setClauses.join(", "))
    //                   .arg("Where name = 'Alice'");

    if (!query.prepare(sql)) {
        qWarning() << "Prepare update SQL with where clause failed:" << query.lastError().text();
        return false;
    }
    bindUpdateParams(query, entity);
    bindParams(query, params);
    // 使用合并后的所有参数
    if (!query.exec()) {
        handleQueryError(query);
        return false;
    }

    return query.numRowsAffected() > 0;
}

template<typename T>
bool BaseMapper<T>::deleteById(int id) {
    validateTableName();
    validateValue(id);

    QSqlQuery query(m_connection);
    QString sql = QString("DELETE FROM %1 WHERE id = :id").arg(MetaDataUtils::tableName<T>());

    if (!query.prepare(sql)) {
        qWarning() << "Prepare delete SQL failed:" << query.lastError().text();
        return false;
    }

    query.bindValue(":id", id);

    if (!query.exec()) {
        handleQueryError(query);
        return false;
    }

    return query.numRowsAffected() > 0;
}

template<typename T>
int BaseMapper<T>::deleteByWrapper(const QueryWrapper& wrapper) {
    validateTableName();

    QSqlQuery query(m_connection);
    QString sql = QString("DELETE FROM %1 %2")
                      .arg(MetaDataUtils::tableName<T>())
                      .arg(wrapper.buildWhereClause());

    // if (!SecurityUtils::isValidSqlFragment(sql)) {
    //     throw SqlInjectionException("Unsafe SQL fragment detected");
    // }

    if (!query.prepare(sql)) {
        qWarning() << "Prepare delete SQL failed:" << query.lastError().text();
        return -1;
    }

    // 使用合并后的所有参数
    QVariantMap params = wrapper.allParamsWithExtra();
    bindParams(query, params);

    if (!query.exec()) {
        handleQueryError(query);
        return -1;
    }

    return query.numRowsAffected();
}

template<typename T>
T BaseMapper<T>::selectById(int id) {
    validateValue(id);

    QueryWrapper wrapper;
    wrapper.eq("id", id);
    QList<T> result = selectList(wrapper);
    return result.isEmpty() ? T() : result.first();
}

template<typename T>
QList<T> BaseMapper<T>::selectList(const QueryWrapper& wrapper) {
    validateTableName();

    QList<T> result;
    QSqlQuery query(m_connection);

    QString sql = QString("SELECT * FROM %1 %2")
                      .arg(MetaDataUtils::tableName<T>())
                      .arg(wrapper.buildSqlClause());

    // if (!SecurityUtils::isValidSqlFragment(sql)) {
    //     throw SqlInjectionException("Unsafe SQL fragment detected");
    // }

    if (!query.prepare(sql)) {
        qWarning() << "Prepare select SQL failed:" << query.lastError().text();
        return result;
    }

    // 使用合并后的所有参数
    QVariantMap params = wrapper.allParamsWithExtra();
    bindParams(query, params);

    if (!query.exec()) {
        handleQueryError(query);
        return result;
    }

    while (query.next()) {
        result.append(extractEntity(query));
    }

    return result;
}

template<typename T>
T BaseMapper<T>::selectOne(const QueryWrapper& wrapper) {
    QueryWrapper limitedWrapper = wrapper;
    limitedWrapper.page(1, 1);
    QList<T> result = selectList(limitedWrapper);
    return result.isEmpty() ? T() : result.first();
}

template<typename T>
int BaseMapper<T>::selectCount(const QueryWrapper& wrapper) {
    validateTableName();

    QSqlQuery query(m_connection);

    QString sql = QString("SELECT COUNT(*) FROM %1 %2")
                      .arg(MetaDataUtils::tableName<T>())
                      .arg(wrapper.buildWhereClause());

    // if (!SecurityUtils::isValidSqlFragment(sql)) {
    //     throw SqlInjectionException("Unsafe SQL fragment detected");
    // }

    if (!query.prepare(sql)) {
        qWarning() << "Prepare count SQL failed:" << query.lastError().text();
        return -1;
    }

    // 使用合并后的所有参数
    QVariantMap params = wrapper.allParamsWithExtra();
    bindParams(query, params);

    if (!query.exec() || !query.next()) {
        handleQueryError(query);
        return -1;
    }

    return query.value(0).toInt();
}

template<typename T>
bool BaseMapper<T>::exists(const QueryWrapper& wrapper) {
    return selectCount(wrapper) > 0;
}

template<typename T>
Transaction BaseMapper<T>::beginTransaction() {
    return Transaction();
}

template<typename T>
QVariantMap BaseMapper<T>::entityToMap(T& entity) {
    QVariantMap map;
    const QMetaObject* meta = &T::staticMetaObject;

    for (int i = 0; i < meta->propertyCount(); ++i) {
        QMetaProperty prop = meta->property(i);
        QByteArray propName = prop.name();
        QVariant value = prop.readOnGadget(&entity);
        map[propName] = value;
    }

    return map;
}

template<typename T>
void BaseMapper<T>::mapToEntity(const QVariantMap& map, T& entity) {
    const QMetaObject* meta = &T::staticMetaObject;

    for (auto it = map.constBegin(); it != map.constEnd(); ++it) {
        int propIndex = meta->indexOfProperty(it.key().toLatin1());
        if (propIndex != -1) {
            QMetaProperty prop = meta->property(propIndex);
            prop.writeOnGadget(&entity, it.value());
        }
    }
}

template<typename T>
QString BaseMapper<T>::buildInsertSql(const T& entity) {
    QStringList placeholders;
    QStringList columnsSql ; //sql语句中需要操作的列
    const QMetaObject* meta = &T::staticMetaObject;
    QStringList columns = MetaDataUtils::columnMap<T>(); //这是
    QVariantMap defaultMapValue = MetaDataUtils::GetDefaultMapValue(entity);
    QString autoIncrement = MetaDataUtils::getAutoIncrement<T>();

    for (int i = 0; i < meta->propertyCount(); ++i) {
        QMetaProperty prop = meta->property(i);
        QByteArray propName = prop.name();
        if(columns.contains(propName))
        {
            if(!defaultMapValue.contains(propName))
            {
                validateColumnName(propName);
                columnsSql << propName;
                placeholders << ":" + propName; //没有default

            }else if(autoIncrement == propName){
                //有自动增长的不要去插入

            }else if(defaultMapValue[propName].toInt() != 0){
                validateColumnName(propName);
                columnsSql << propName;
                placeholders << ":" + propName;
            }
        }

    }

    return QString("INSERT INTO %1 (%2) VALUES (%3)")
        .arg(MetaDataUtils::tableName<T>())
        .arg(columnsSql.join(", "))
        .arg(placeholders.join(", "));
}

template<typename T>
void BaseMapper<T>::bindInsertParams(QSqlQuery& query, T& entity) {
    const QMetaObject* meta = &T::staticMetaObject;
    QStringList colMap = MetaDataUtils::columnMap<T>();
    QVariantMap defaultMapValue = MetaDataUtils::GetDefaultMapValue(entity);
    QStringList defaultColumns = MetaDataUtils::DefaultMap<T>(); //获取

    for (int i = 0; i < meta->propertyCount(); ++i) {
        QMetaProperty prop = meta->property(i);
        QByteArray propName = prop.name();

        //QString column = colMap.value(propName, propName);
        //首先如果是有 主键，且，主键是自动插入的，那么就不需要insert

        if(!defaultMapValue.contains(propName+"_Default") )
        {
            QVariant value = prop.readOnGadget(&entity);
            validateValue(value);
            query.bindValue(":" + propName, value);
        }else if(defaultMapValue[propName+"_Default"].toInt() != 0){
            QVariant value = prop.readOnGadget(&entity);
            validateValue(value);
            query.bindValue(":" + propName, value);
        }
    }
}

template<typename T>
QString BaseMapper<T>::buildUpdateSql(const T& entity) {
    QStringList sets;
    const QMetaObject* meta = &T::staticMetaObject;
    QStringList columns = MetaDataUtils::columnMap<T>();
    QString primaryKeyColumn = "";
    QString primaryKey = MetaDataUtils::getPrimaryKeyMap<T>();
    if(MetaDataUtils::getPrimaryKeyMap<T>().count() != 0)  {
        //1. 说明有主键
        primaryKeyColumn = MetaDataUtils::getPrimaryKeyMap<T>() ;
    }

    for (int i = 0; i < meta->propertyCount(); ++i) {
        QMetaProperty prop = meta->property(i);
        QByteArray propName = prop.name();
        QVariant value = prop.readOnGadget(&entity);
        // ID不包含在SET子句中

        //当前属性名， colMap是当前 表的列明对应的属性名，
        if (propName == primaryKey ) {
            continue;
        }else if (value.isNull()) {
            continue;
        }else if(!value.isValid()) {
            continue;
        }else if(value.userType() == QMetaType::QDateTime ){
            QDateTime dt = value.toDateTime();
            if (!dt.isValid()) {
                continue;
            }else if(columns.contains(propName)) {
                validateColumnName(propName);
                sets << QString("%1 = :SET_%2").arg(propName).arg(propName);
            }
        }else if(value.userType() == QMetaType::QDate){
            QDate date = value.toDate();
            if (!date.isValid()) {
                continue;
            }else if(columns.contains(propName)){
                validateColumnName(propName);
                sets << QString("%1 = :SET_%2").arg(propName).arg(propName);
            }
        }else if(columns.contains(propName)){
            //QString column = colMap.value(propName, propName);
            validateColumnName(propName);
            sets << QString("%1 = :SET_%2").arg(propName).arg(propName);
        }
    }   
    return QString("UPDATE %1 SET %2 WHERE id = :SET_id")
        .arg(MetaDataUtils::tableName<T>())
        .arg(sets.join(", "));
}

template<typename T>
void BaseMapper<T>::bindUpdateParams(QSqlQuery& query, T& entity) {
    const QMetaObject* meta = &T::staticMetaObject;

    for (int i = 0; i < meta->propertyCount(); ++i) {
        QMetaProperty prop = meta->property(i);
        QByteArray propName = prop.name();
        QVariant value = prop.readOnGadget(&entity);
        validateValue(value);
        query.bindValue(":SET_" + propName, value);
    }
}

template<typename T>
T BaseMapper<T>::extractEntity(const QSqlQuery& query) {
    T entity;
    const QMetaObject* meta = &T::staticMetaObject;
    QStringList colMap = MetaDataUtils::columnMap<T>();

    for (int i = 0; i < meta->propertyCount(); ++i) {
        QMetaProperty prop = meta->property(i);
        QByteArray propName = prop.name();

        if(colMap.contains(propName)) {
            if (query.isValid() && query.record().indexOf(propName) != -1) {
                QVariant value = query.value(propName);
                prop.writeOnGadget(&entity,value);
            }
        }
    }

    return entity;
}

template<typename T>
void BaseMapper<T>::bindParams(QSqlQuery& query, const QVariantMap& params) {
    for (auto it = params.constBegin(); it != params.constEnd(); ++it) {
        QString placeholder = ":" + it.key();

        // 检查占位符是否在SQL语句中
        if (query.lastQuery().contains(placeholder)) {
            validateValue(it.value());
            query.bindValue(placeholder, it.value());
        }
    }
}

template<typename T>
void BaseMapper<T>::handleQueryError(const QSqlQuery& query) {
    QString errorMsg = query.lastError().text();
    QString executedSql = query.executedQuery();

    qWarning() << "SQL execution error:" << errorMsg;
    qWarning() << "Executed SQL:" << executedSql;
    qWarning() << "Bound values:" << query.boundValues();
}

} // namespace QtMyBatisPlus



#endif // QT_MYBATIS_PLUS_H
